
#include <jive/app/declare.h>
#include <jive/app/ChainModule.h>
#include <jive/app/ControlModule.h>
#include <jive/app/OutputModule.h>
#include <jive/app/ReportModule.h>
#include <jive/app/Application.h>
#include <jive/app/InfoModule.h>
#include <jive/app/UserconfModule.h>
#include <jive/geom/declare.h>
#include <jive/model/declare.h>
#include <jive/femodel/declare.h>
#include <jive/fem/declare.h>
#include <jive/fem/InputModule.h>
#include <jive/fem/InitModule.h>
#include <jive/fem/ShapeModule.h>
#include <jive/mesh/BndgenModule.h>
#include <jive/implict/declare.h>
#include <jive/implict/NonlinModule.h>
#include <jive/gl/declare.h>
#include <jive/gl/DisplayModule.h>
#include "import.h"
#include "models.h"


using jive::app::Application;
using jive::app::Module;
using jive::app::ChainModule;
using jive::app::InfoModule;
using jive::app::ControlModule;
using jive::app::ReportModule;
using jive::app::UserconfModule;
using jive::fem::InputModule;
using jive::fem::InitModule;
using jive::fem::ShapeModule;
using jive::mesh::BndgenModule;
using jive::implict::NonlinModule;
using jive::gl::DisplayModule;


//-----------------------------------------------------------------------
//   mainModule
//-----------------------------------------------------------------------


Ref<Module> mainModule ()
{
  using jem::newInstance;

  Ref<ChainModule>    chain = newInstance<ChainModule> ();
  Ref<ControlModule>  ctrl;


  jive::app::declareModules    ();
  jive::geom::declareIShapes   ();
  jive::model::declareModels   ();
  jive::femodel::declareModels ();
  jive::implict::declareModels ();
  jive::fem::declareMBuilders  ();
  jive::gl::declareModules     ();

  declarePhaseFieldModel ();

  chain->pushBack ( newInstance<InputModule>     () );
  chain->pushBack ( newInstance<ShapeModule>     () );
  chain->pushBack ( newInstance<BndgenModule>    () );
  chain->pushBack ( newInstance<InitModule>      () );
  chain->pushBack ( newInstance<InfoModule>      () );
  chain->pushBack ( newInstance<NonlinModule>  () );

  ctrl = newInstance<ControlModule> (
    "control",
    newInstance<UserconfModule> ( "extra" )
  );
  ctrl ->runWhile ( "i < 0" );

  chain->pushBack ( ctrl );

  return newInstance<DisplayModule> (newInstance<ReportModule> ( "report", chain ) );
}


//-----------------------------------------------------------------------
//   main
//-----------------------------------------------------------------------


int main ( int argc, char** argv )
{
  return Application::exec ( argc, argv, & mainModule );
}

// exec:
// 1. creates props from input file
// 2. creates globdat
// 3. creates the mainModule
// 4. call the init function of each module in the order defined (e.g. the init of InitModule creates the models: it calls the constructor (ElasticModel in this case) to create all models (i.e. model.model.solid ...) and configure)
// 5. calls the run function of each module (e.g. LinsolveModules assembles and solves the system equation and update globdat)
// 6. the LinsolveModule calls the TakeAction function of the top level model, which in turns propagates to child models
